//泛型   广泛的类型

{
  //声明一个函数  创建一个包含 `count` 个 `value` 的数组
  // <T> 类型参数.  类型参数的名字是可以自定义的. 一般只需要一个字母即可. 常见的参数名, T, K, V, R
  // 当参数的类型不固定的时候, 应该要想到泛型
  function createArray<T>(count: number, value: T) {
    //声明一个数组
    let arr: T[] = [];
    //循环
    for (let i = 0; i < count; i++) {
      //向 arr 中压入数据 value
      arr.push(value);
    }
    //返回
    return arr;
  }

  //调用函数
  let result = createArray<string>(10, "abc");
  // result[0].    //这里有提示
  // result[0].toFixed(2);// 这里有报错
}

{
  //具有类型参数的函数, 称之为『泛型函数』
  function createArray<T, K>(a: T, b: K): [T, K] {
    return [a, b];
  }

  //传入类型参数, 调用函数
  // let result = createArray<string, number>('今天是平安夜', 28);
  //不传入类型参数
  let result = createArray("今天是平安夜", 28);
  // result[0].
  // result[1].map();
}

{
  //声明接口  具有类型参数的接口, 称之为『泛型接口』
  interface Response<T> {
    status: number;
    headers: object;
    data: T;
  }

  interface User {
    id: number;
    username: string;
    email: string;
  }

  //声明对象
  let res: Response<User> = {
    status: 200,
    headers: {},
    data: {
      id: 1,
      username: "zhangsan",
      email: "zz@qq.com",
    },
  };

  interface Book {
    id: number;
    title: string;
    author: string;
  }

  let res2: Response<Book> = {
    status: 200,
    headers: {},
    data: {
      id: 1,
      title: "西游记",
      author: "吴承恩",
    },
  };
}

{
  // 在接口名后边编写 <T> 里面的 T 是形参
  interface Response<T> {
    status: number;
    headers: object;
    data: T;//在结构中在 接口后使用 <T>, 这个 T 是实参
  }

  interface ResponseBody<T>{
    code: string;
    msg: string;
    data: T
  }

  interface User {
    id: number;
    username: string;
    email: string;
  }
  //声明对象
  let res: Response<ResponseBody<User>> = {
    status: 200,
    headers: {},
    data: {
      code: "20000",
      msg: "请求成功",
      data: {
        id: 1,
        username: "zhangsan",
        email: "zz@qq.com",
      },
    },
  };

  interface Book {
    id: number;
    title: string;
    author: string;
  }

  let res2: Response<ResponseBody<Book>> = {
    status: 200,
    headers: {},
    data: {
      code: "20000",
      msg: "请求成功",
      data: {
        id: 1,
        title: '红楼梦',
        author: "曹雪芹"
      },
    },
  };
}


{
  //泛型类
  class Container<T>{
    //容器数组
    store: T[] = [];

    //向数组中压入数据
    push(v: T): number{
      this.store.push(v);
      return this.store.length;
    }

    //获取store中第一个元素
    getFirst(): T{
      return this.store[0];
    }
  }

  //实例化
  let c = new Container<string>();
  c.push('圣诞快乐');
  //获取第一个元素
  let first = c.getFirst();
  // first.map();
}

{
  //定义一个接口
  interface HasLength{
    length: number;
  }
  //泛型约束 获取某一个数据的 length 属性
  function getLength<T extends HasLength>(value: T){
    return value.length;
  }

  console.log(getLength('111'));
  // console.log(getLength(123));//这里会报错

}